package model.loader;

import model.objects.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import physics.EuclideanVector;
import physics.PhysicsManager;
import physics.collision.CollisionStrategy;
import physics.movement.MovementStrategy;
import util.XMLUtils;

import javax.swing.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class GameFactory {

    public static Level loadLevel(File levelFile, ImageMap map) {
        Level newLevel = new Level();

        Document dom = XMLUtils.initializeDocument(levelFile);

        NodeList objectList = dom.getElementsByTagName("gameobject");
        for (int i = 0; i < objectList.getLength(); i++) {
            // <gameobject> node
            Node node = objectList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) node;

                String tag = element.getAttribute("tag");

                int x = XMLUtils.getTagInt("x", element);
                int y = XMLUtils.getTagInt("y", element);
                int width = XMLUtils.getTagInt("width", element);
                int height = XMLUtils.getTagInt("height", element);

                Rectangle bounds = new Rectangle(x, y, width, height);
                GameImage gm = map.getGameImageByTag(tag);
                List<Image> images = new ArrayList<Image>();
                if (gm != null) {
                    images.addAll(gm.getImages());
                }

                CollisionStrategy collision = CollisionStrategyFactory.fromTagValue(XMLUtils.getTagValue("collision", element));
                Node movementNode = XMLUtils.getSingleNode("movement", element);
                MovementStrategy movement = MovementStrategyFactory.fromNode(movementNode);
                GameObject gameObject = new GameObject(newLevel, bounds, images, collision, movement);
                if (tag.equals("hero")) {
                    newLevel.addHero(gameObject);
                } else {
                    newLevel.add(gameObject);

                }
            }
        }

        // extract global forces from level file
        NodeList forces = dom.getElementsByTagName("force");
        for (int i = 0; i < forces.getLength(); i++) {
            Node force = forces.item(i);
            if (force.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) force;
                int x = XMLUtils.getTagInt("x", element);
                int y = XMLUtils.getTagInt("y", element);
                newLevel.addGlobalForce(new EuclideanVector(x, y));
            }

        }
        return newLevel;
    }

    public static PhysicsManager loadForces(File forcesFileName) {
        List<EuclideanVector> vectors = new ArrayList<EuclideanVector>();
        Document dom = XMLUtils.initializeDocument(forcesFileName);

        NodeList forces = dom.getElementsByTagName("force");
        for (int i = 0; i < forces.getLength(); i++) {
            Node force = forces.item(i);
            if (force.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) force;
                int x = XMLUtils.getTagInt("x", element);
                int y = XMLUtils.getTagInt("y", element);
                vectors.add(new EuclideanVector(x, y));
            }

        }
        return new PhysicsManager(vectors);
    }

    public static ImageMap loadImages(File imageConfig) {
        ImageMap imageMap = new ImageMap();

        Document dom = XMLUtils.initializeDocument(imageConfig);

        NodeList imageList = dom.getElementsByTagName("image");
        // process each <image> tag
        for (int i = 0; i < imageList.getLength(); i++) {
            Node node = imageList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                String tag = ((Element) node).getAttribute("id");
                // get the node children
                NodeList children = ((Element) node).getElementsByTagName("file");
                for (int j = 0; j < children.getLength(); j++) {
                    Node file = children.item(j);
                    String imageFileName = XMLUtils.getTagValue(file);
                    NamedImage namedImage = new NamedImage(imageFileName, XMLUtils.fileNameToImage(imageConfig, imageFileName));
                    GameImage gameImage = new GameImage(tag, namedImage);
                    imageMap.insertImageByTag(tag, gameImage);
                }


            }
        }
        return imageMap;
    }








}
